package com.xc.pay.weixin.template.Base;

import cn.hutool.json.JSONObject;
import com.wechat.pay.contrib.apache.httpclient.Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.xc.pay.weixin.constant.WxProperties;
import com.xc.pay.weixin.properties.base.WxPayBaseProperties;
import com.xc.pay.weixin.util.WxToolUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;

import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.Base64;

/**
 * Base实现 构造HttpClient
 *
 * @author rongrong
 * @date 2020/12/3
 */
@Slf4j
public abstract class WxPayTemplateClient implements WxPayBaseTemplate {

  public HttpClient httpClient = null;
  public WxPayBaseProperties properties;
  private Credentials credentials;
  private PrivateKey privateKey;

  public void setProperties(WxPayBaseProperties properties) {
    this.properties = properties;
  }

  /**
   * 构造Template方法
   *
   * @param privateKeyPath xxx_key.pem证书路径
   * @param privateCertPath xxx_cert.pem证书路径
   * @param certSerialNumber 证书序列号
   * @param apiV3Key apiV3密钥
   * @param mchid 商户号
   */
  public void build(
      String privateKeyPath,
      String privateCertPath,
      String certSerialNumber,
      String apiV3Key,
      String mchid) {
    JSONObject obj =
        this.initApiV3HttpClient(
            privateKeyPath, privateCertPath, certSerialNumber, apiV3Key, mchid);
    httpClient = obj.get("httpClient", HttpClient.class);
    credentials = obj.get("credentials", WechatPay2Credentials.class);
    privateKey = obj.get("privateKey", PrivateKey.class);
  }

  /**
   * 生成签名信息
   *
   * @return String
   */
  @SneakyThrows
  public JSONObject getSignReturn() {
    final JSONObject jsonObject = new JSONObject();
    // 请求方式
    final HttpGet get = new HttpGet();
    // 设置请求地址
    get.setURI(new URI(WxProperties.DOWNLOAD_CERT_URL));
    final String str = WxToolUtil.getNonceStr();
    final String timestamp = WxToolUtil.getTimestamp();
    jsonObject
        .putOpt("appid", properties.getAppid())
        .putOpt("partnerid", properties.getMchid())
        .putOpt("noncestr", str)
        .putOpt("timestamp", timestamp)
        .putOpt("package", "Sign=WXPay");
    // 获取签名 start
    String message =
        "GET" + "\n" + WxProperties.CERT_URL + "\n" + timestamp + "\n" + str + "\n" + "" + "\n";
    // 签名
    Signature sign = Signature.getInstance("SHA256withRSA");
    sign.initSign(privateKey);
    sign.update(message.getBytes(StandardCharsets.UTF_8));
    // 生成token信息
    String token =
        "mchid=\""
            + "getMerchantId"
            + "\","
            + "nonce_str=\""
            + str
            + "\","
            + "timestamp=\""
            + timestamp
            + "\","
            + "serial_no=\""
            + properties.getCertSerialNumber()
            + "\","
            + "signature=\""
            + Base64.getEncoder().encodeToString(sign.sign())
            + "\"";
    final String auth = credentials.getSchema() + " " + token;
    get.setHeader("Authorization", auth);
    final HttpResponse response = httpClient.execute(get);
    int statusCode = response.getStatusLine().getStatusCode();
    String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
    if (HttpStatus.SC_OK == statusCode || HttpStatus.SC_NO_CONTENT == statusCode) {
      log.info(
          "\n【请求地址】：{}\n【请求数据】：{}\n【响应数据】：{}",
          WxProperties.DOWNLOAD_CERT_URL,
          auth,
          responseString);
      jsonObject.putOpt("paySign", responseString);
    } else {
      throw new RuntimeException("获取签名错误");
    }
    return jsonObject;
  }
}
